Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite animation logic #6845

Merged
merged 5 commits into from
Dec 27, 2019
Merged

Rewrite animation logic #6845

merged 5 commits into from
Dec 27, 2019

Conversation

kurkle
Copy link
Member

@kurkle kurkle commented Dec 17, 2019

Some small chores 🤣

Minimized size is reduced by 742 bytes, so nothing big there.
This replaces the whole animation logic to target individual properties. Everything can be animated separately, with different duration, delay, easing etc.
Animation configuration can be extended at dataset level, to reduce the need for scriptable animations. Also active, resize keys are added to further reduce need for scripting.
Tooltip has its own animation configuration.

This is greatly inspired by @simonbrunel WIP on datalabels that he showed me many months ago.

Demo

TODO:

  • Documentation
  • Add more default properties (at least tension needs to be added)
  • Samples

Copy link
Contributor

@benmccann benmccann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow, amazing!!!

},
numbers: {
type: 'number',
properties: ['x', 'y', 'borderWidth', 'radius']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add something to animations.md or elsewhere in the new docs about these new options?

We used to figure this out dynamically at runtime, which would reduce the chance for user error forgetting to add something here. Does that have a big performance impact though?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was hesitant to add property type based fallback, but did not really test the impact on performance.

If that could be disabled in config, then I guess it would be ideal. I think this could be left for a later MR though.

// all borders are drawn for floating bar
/* TODO: float bars border skipping magic
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if you want to fix in this one or a follow-up, but just a reminder that this is here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kind of don't like this kind of things in the code. We don't really know if the user wants to draw all borders in the float bar. It could be default though, but that's kind of hard because float bar does not have its own type.

So this could be "fixed" in many ways and has little to do with the animations.

  • it could be just documented, so users can add the config
  • we could separate floatBar to its own type and provide defaults
  • we could continue overwriting any user config here (not my favorite)
    • I think I did not do that because those "shared" properties were frozen initially and this caused problems. I ended up removing the freezing though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should just leave it as is for now and handle any change in a separate PR since it's not really related to the animation

for (i = 0, ilen = points.length; i < ilen; ++i) {
points[i].pivot(me.chart._animationsDisabled);
// Update Points
if (meta.visible) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we bail out sooner if not visible? i.e. before updating the line

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think some tests failed if I did that, but I could have changed something after that.
This is done to keep the points where they are, when hiding from the legend. (so no movement when shown back, especially when the line is the only one and scale is determining its range automatically)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 filler related tests fail in that case. I can re-check if either this or #6795 gets merged.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot more tests fail now, because options would not be set to line and those are expected in _getMaxOverflow for example.

src/core/core.datasetController.js Show resolved Hide resolved
src/core/core.datasetController.js Outdated Show resolved Hide resolved
return animation.chart === chart;
});
/**
* @private
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a little bit of documentation here about how $shared works? That part seems a little complicated

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do, just commenting here also.

If options are cacheable (= not scripted or indexed), those are shared between elements.

Those shared options are then animated separately. So having one animation object per common point option, like radius. This is mostly why the demo is so fast compared to master where every point's every property is interpolated.

This could be still improved - we could have some of the options shared and some unique to point. But lets leave that for later, if ever.

(talking about point here, because its the element that is usually numerous. applies to bar as well.)

src/core/core.animator.js Outdated Show resolved Hide resolved
src/core/core.controller.js Outdated Show resolved Hide resolved
docs/configuration/tooltip.md Show resolved Hide resolved
src/controllers/controller.bar.js Show resolved Hide resolved

defaults._set('bubble', {
animation: {
numbers: {
properties: ['x', 'y', 'borderWidth', 'radius']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no type field here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is extending the default animation, so type is inherited.

@kurkle
Copy link
Member Author

kurkle commented Dec 19, 2019

Update:

  • Some docs
  • Added couple of samples
  • Made callbacks work (almost) like before
  • More default animated properties (colors[border, background], base, tension)

@benmccann
Copy link
Contributor

@kurkle it looks like there's a file that will need to be rebased

Copy link
Contributor

@benmccann benmccann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Run grep -ri duration docs/ to get a list of some more docs that need to be updated. The migration guide should probably be updated to match those updates as well

docs/configuration/animations.md Show resolved Hide resolved
docs/configuration/animations.md Show resolved Hide resolved
duration: 0
},
numbers: {
type: 'number',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems a little redundant to have to specify type when it's already specified as the key. Could we just use the key?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key name is arbitrary, I just ended up choosing numbers. It could be anything.

I'm actually not sure if this is a good way of specifying defaults. Maybe those should be under defaults, so those can be disabled easily:

animation: {
  defaults: false,
  location: { // multiple properties targeted
    type: 'number',
    properties: ['x', 'y', 'base']
    easing: 'linear',
    duration: 200
  },
  dimensions: { // multiple
    type: 'number',
    properties: ['width', 'height'],
    duration: 400,
    easing: 'easeOutElastic'
  },
  multiKeyBackground: { // single
    type: 'color',
    easing: 'linear'
  }
}

But these things that can be altered when people start trying out things (alpha).

docs/configuration/animations.md Show resolved Hide resolved
@kurkle
Copy link
Member Author

kurkle commented Dec 22, 2019

Update2:

  • more docs
  • another sample (loop)
  • small tweaks to the active, separated mode and context.active.
    • 'active' config is also used when removing hover styles, context.active can be used to differentiate these.

Demo now contains the samples too.

@leeoniya
Copy link

another sample (loop)

after "Remove Dataset", "Add Data" is busted.

@kurkle
Copy link
Member Author

kurkle commented Dec 22, 2019

after "Remove Dataset", "Add Data" is busted.

Thats issue #6839

Copy link
Contributor

@benmccann benmccann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm really excited about this! it looks pretty close to me. I only have a few minor comments

// all borders are drawn for floating bar
/* TODO: float bars border skipping magic
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should just leave it as is for now and handle any change in a separate PR since it's not really related to the animation

src/controllers/controller.line.js Outdated Show resolved Hide resolved
src/core/core.animator.js Outdated Show resolved Hide resolved
src/core/core.controller.js Outdated Show resolved Hide resolved
src/core/core.datasetController.js Show resolved Hide resolved
src/core/core.datasetController.js Outdated Show resolved Hide resolved
benmccann
benmccann previously approved these changes Dec 24, 2019
Copy link
Contributor

@benmccann benmccann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm besides @etimberg's one suggestion for the docs. there's a lot here, so I may have missed something, but it seems like a big improvement overall and we will have some time to play with it before v3 is released. thanks for this! it's a really great change!

etimberg
etimberg previously approved these changes Dec 24, 2019
@kurkle kurkle dismissed stale reviews from etimberg and benmccann via 30d4759 December 27, 2019 07:58
@kurkle
Copy link
Member Author

kurkle commented Dec 27, 2019

Added 'none' to api.md.

Some future thoughts:
'hide' and 'show' modes. Needs couple of functions and make Legend use those. hide(datasetIndex, index) and show(datasetIndex, index).

Been also thinking about 'init' and some predefined string values for from / to:

animations: {
  init: {
    y: {
      from: 'base'
    }
  }
}

These predefined strings could be 'top', 'bottom', 'left', 'right' and 'base' (maybe more). These would relate to chartArea.

* **duration** (number): Time for the animation of the redraw in milliseconds
* **lazy** (boolean): If true, the animation can be interrupted by other animations
* **easing** (string): The animation easing function. See [Animation Easing](../configuration/animations.md) for possible values.
A `mode` string can be provided to indicate what should be updated and what animation configuration should be used. Core calls this method using any of `undefined`, `'reset'`, `'resize'` or `'active'`. `'none'` is also a supported mode for skipping animations for single update.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does undefined do? Is it the same as 'none'?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about 'reset'? Is .update('reset') the same as or related to .reset()?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its the default/normal update. Uses configure animations.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reset: function() {
	this._update('reset');
},

@etimberg etimberg merged commit b83f64b into chartjs:master Dec 27, 2019
@etimberg
Copy link
Member

After merging I got an email that the build broke

@kurkle
Copy link
Member Author

kurkle commented Dec 27, 2019

Triggered rebuild and it passed. Not sure what caused this. Its always tarvis through.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants